package com.bw.lib_common.vm

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.bw.lib_common.coroutine.CoroutineHelper
import com.bw.lib_common.entity.Res
import kotlinx.coroutines.*
import java.util.concurrent.Executors

/**
 * 基础ViewModel
 */
abstract class BaseViewModel3:ViewModel() {


    /**
     * 协程中如何处理异常
     * 1.try-catch
     * 2.自定义CoroutineExceptionHandLer（协程异常处理类）
     * 3.创建独立作用域 SupervisorJob 异常对其他协程没影响
     */

    val onFailed by lazy { MutableLiveData<Throwable>() }

//    //自定义协程的线程池
//    protected val threadPool = Executors.newFixedThreadPool(16).asCoroutineDispatcher()
//
//    //单线程协程调度器
//    protected val dispatcher = newSingleThreadContext("SingleThreadDisPatcher")
//
//    //固定线程协程作用域
//    protected val dispatcher2 = newFixedThreadPoolContext(16,"FixedThreadDispatcher")
//
//    //错误信息
//    protected val ErrorLiveData=MutableLiveData<String>()
//
//    protected val SuccessLiveData= mutableListOf<String>()


    fun <T> executeNetwork(
        //suspend 挂起方法,也就是apiService中的请求方法,() -> 代表当前参数是一个方法,Res代表当前方法的返回值
        s: suspend () -> Res<T>,
        //成功的LiveData,会把s的返回值中的values添加到success中
        success: (T) -> Unit,
        //失败的LiveData,会把失败的信息(Throwable)直接传递到通用的onFailed的postValue方法中
        failed: (Throwable) -> Unit = onFailed::postValue,
        okCode: Int = 200
    ) {
        /**
         * 协程调度器,Unconfined代表没有特殊指定
         * DEFAULT代表在业务线程中启动协程
         * 使用postValue返回主线程
         */
        CoroutineHelper.myModelScope.launch(CoroutineHelper.mDispatcher1) {
            try {
                val res = s.invoke()
                if (res.code == okCode) {
                    success(res.data)
                } else {
                    failed(RuntimeException(res.message))
                }

            } catch (e: Exception) {

                failed(e)
            }
        }
    }



    fun <T> executeNotResNetwork(
        s: suspend () -> T,
        success: (T) -> Unit,
        failed: (Throwable) -> Unit = onFailed::postValue,
    ) {

        CoroutineHelper.myModelScope.launch(
            context = CoroutineHelper.mDispatcher1,
            start = CoroutineStart.LAZY
        ) {
            try {
                val res = s.invoke()
                success(res)
            } catch (e: Exception) {
                failed(e)
            }
        }.start()
    }



}
